﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Newtonsoft.Json.Linq;
using System.Web;
using SeoWebSite.Model;
using SeoWebSite.Common.DEncrypt;
using System.Configuration;
using System.IO;
using System.Collections;
using SeoWebSite.Common;
using System.Reflection;

namespace SeoWebSite.BLL
{
    public class OS
    {
        QOModulesBLL modulesbll = new QOModulesBLL();
        QOLibrariesBLL librariesbll = new QOLibrariesBLL();
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="user"></param>
        /// <param name="pass"></param>
        /// <param name="group_id"></param>
        /// <returns></returns>
        public string Login(string user, string pass, string group_id)
        {
            QOMembersBLL memberbll = new QOMembersBLL();

            if (string.IsNullOrEmpty(user))
            {
                return "{errors:[{id:'user', msg:'必须填写'}]}";
            }
            if (string.IsNullOrEmpty(pass))
            {
                return "{errors:[{id:'pass', msg:'必须填写'}]}";
            }
            if (!memberbll.Exists(user))
            {
                return "{errors:[{id:'user', msg:'没有找到该成员'}]}";
            }
            if (!memberbll.IsActive(user))
            {
                return "{errors:[{id:'user', msg:'此帐户没有激活'}]}";
            }
            string member_id = memberbll.Get_ID(user, pass, true);
            if (string.IsNullOrEmpty(member_id))
            {
                return "{errors:[{id:'user', msg:'登录失败'}]}";
            }
            if (string.IsNullOrEmpty(group_id))
            {
                QOGroupsHasMembersBLL groupbll = new QOGroupsHasMembersBLL();
                DataSet ds = groupbll.get_by_member_id(member_id, true);
                if (ds.Tables[0].Rows.Count == 0)
                {
                    return "{errors:[{id:'user', msg:'该账户没有加入组'}]}";
                }
                else if (ds.Tables[0].Rows.Count > 1)
                {
                    return "{success:true, groups: " + JArray.FromObject(ds.Tables[0]) + "}";
                }
                group_id = ds.Tables[0].Rows[0]["qo_groups_id"].ToString();
            }
            try
            {
                QOSessionsBLL sessionsbll = new QOSessionsBLL();
                QOSessions model = new QOSessions();
                model.id = HashEncode.GetSecurity().Substring(0, 32);
                model.qo_members_id = int.Parse(member_id);
                model.qo_groups_id = int.Parse(group_id);
                model.ip = System.Web.HttpContext.Current.Request.UserHostAddress;
                model.date = DateTime.Now;
                sessionsbll.Add(model);
                return "{success: true, sessionId: '" + model.id + "'}";
            }
            catch (Exception)
            {
                return "{errors: [{id: 'user', msg: '登录失败'}]}";
            }
        }


        public bool session_exists()
        {
            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            return sessionsbll.Exists();
        }

        public void init()
        {
            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            sessionsbll.set_data("");
        }

        public string print_module_css()
        {
            string csshtml = "";
            DataSet ds = modulesbll.GetList("active=1");
            csshtml += this.print_css(ds, "MODULES_DIR");
            ds = librariesbll.GetList("active=1");
            csshtml += this.print_css(ds, "LIBRARIES_DIR");
            return csshtml;
        }


        private string print_css(DataSet ds,string app_dir)
        {
            string modules_dir = ConfigurationManager.AppSettings[app_dir];
            List<string> cssLinkList = new List<string>();
            string cssStr = "<link rel='stylesheet' type='text/css' href='{0}' />\n";
            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                string json = dr["data"].ToString();
                JObject jo = JObject.Parse(json);
                if (jo.SelectToken("client.css") != null)
                {
                    foreach (JObject css in jo.SelectToken("client.css").ToArray())
                    {
                        string directory = (string)css["directory"];
                        foreach (string file in css["files"])
                        {
                            cssLinkList.Add(string.Format(cssStr, modules_dir + directory + file));
                        }
                    }
                }
            }
            return string.Join("\n", cssLinkList.ToArray());
        }

        public string get_member_id()
        {
            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            return sessionsbll.get_member_id();
        }

        public string group_id()
        {
            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            return sessionsbll.get_group_id();
        }

        public string get_member_preference(string member_id, string group_id)
        {
            if (string.IsNullOrEmpty(member_id) || string.IsNullOrEmpty(group_id))
            {
                return null;
            }
            QOPreferencesBLL preferencesbll = new QOPreferencesBLL();
            string json = preferencesbll.get(member_id, group_id);
            if (string.IsNullOrEmpty(json))
            {
                json = preferencesbll.get("0", "0");
            }
            return json;
        }

        public List<QOModules> get_modules()
        {
            List<QOModules> valid_modules = new List<QOModules>();
            QOModulesBLL bll = new QOModulesBLL();
            List<string> ids = this.get_valid_module_ids();
            if (ids != null)
            {
                foreach (string item in ids)
                {
                    QOModules module = bll.get_by_id(item);
                    if (module != null)
                    {
                        valid_modules.Add(module);
                    }
                }
                return valid_modules;
            }
            List<QOModules> active_modules = bll.get_active();
            if (active_modules.Count > 0)
            {
                JObject arg = new JObject();
                List<string> valid_ids = new List<string>();
                foreach (QOModules item in active_modules)
                {
                    valid_ids.Add(item.id);
                    valid_modules.Add(item);
                }
            }
            return valid_modules;
        }

        private List<string> get_valid_module_ids()
        {
            List<string> ids = new List<string>();
            QOSessionsBLL bll = new QOSessionsBLL();
            JObject d = bll.get_data("");
            if (d["module"] != null)
            {
                foreach (string item in d["module"])
                {
                    if (d["valid"] != null && (int)d["valid"] == 1)
                    {
                        ids.Add(item);
                    }
                }
            }
            if (ids.Count > 0)
            {
                return ids;
            }
            return null;
        }

        public string load_module(string module_id)
        {
            if (!string.IsNullOrEmpty(module_id))
            {
                JObject item = new JObject();
                item.Add("id", module_id);
                item.Add("type", "module");
                return this.print_item_javascript(item);
            }
            return null;
        }

        private string print_item_javascript(JObject item)
        {
            string s = "";
            if (!this.is_item_javascript_loaded(item))
            {
                if ((string)item["type"] == "library")
                {
                    s = this.print_library_javascript((string)item["id"]);
                }
                else if ((string)item["type"] == "module")
                {
                    s = this.print_module_javascript((string)item["id"]);
                }
                this.set_item_javascript_loaded(item);
            }
            return s;
        }

        private void set_item_javascript_loaded(JObject item)
        {
            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            string type = (string)item["type"];
            string id = (string)item["id"];
            JObject data = sessionsbll.get_data("");
            if (data[type] == null)
            {
                data.Add(type, JObject.Parse("{" + id.Replace("-", "") + ": {loaded:{javascript :1}}}"));
            }
            else
            {
                ((JObject)data[type]).Add(new JProperty(id, JObject.Parse("{loaded:{javascript :1}}")));
            }
            sessionsbll.set_data(data.ToString());;
        }

        private string print_items_javascript(JArray items)
        {
            string s = "";
            foreach (JObject item in items)
            {
                if (!this.is_item_javascript_loaded(item))
                {
                    if ((string)item["type"] == "library")
                    {
                        s += this.print_library_javascript((string)item["id"]);
                    }
                    else if ((string)item["type"] == "module")
                    {
                        s += this.print_module_javascript((string)item["id"]);
                    }
                    this.set_item_javascript_loaded(item);
                }
            }
            return s;
        }

        private string print_module_javascript(string module_id)
        {
            string s = "";
            QOModulesBLL modulesbll = new QOModulesBLL();
            string dependencies = modulesbll.get_dependencies(module_id);
            if (dependencies != null)
            {
                s += this.print_items_javascript(JArray.Parse(dependencies));
            }
            List<string> files = modulesbll.get_client_files(module_id, "javascript");
            string library_dir = ConfigurationManager.AppSettings["MODULES_DIR"];
            
            foreach (string file in files)
            {
                s += Assistant.file_get_contents(library_dir + file);
            }

            s += this.print_module_locale(module_id);
            return s;
        }

        private string print_module_locale(string module_id)
        {
            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            QOModulesBLL modulesbll = new QOModulesBLL();
            string member_id = sessionsbll.get_member_id();
            string member_locale = "";
            if (!string.IsNullOrEmpty(member_id))
            {
                member_locale = this.get_member_locale(member_id);
            }
            return modulesbll.get_locale_string(module_id, member_locale);
        }

        private string get_member_locale(string member_id)
        {
            QOMembersBLL membersbll = new QOMembersBLL();
            return membersbll.get_locale(member_id);
        }

        private string print_library_javascript(string library_id)
        {
            string s = "";
            QOLibrariesBLL librariesbll = new QOLibrariesBLL();
            string dependencies = librariesbll.get_dependencies(library_id);
            if (dependencies != null)
            {
                s += this.print_items_javascript(JArray.Parse(dependencies));
            }
            List<string> files = librariesbll.get_client_files(library_id, "javascript");
            string library_dir = ConfigurationManager.AppSettings["LIBRARIES_DIR"];
            
            foreach (string file in files)
            {
                s += Assistant.file_get_contents(library_dir + file);
            }
            return s;
        }

        private bool is_item_javascript_loaded(JObject item)
        {
            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            JObject data = sessionsbll.get_data("");
            if (data.SelectToken(item["type"] + "." + item["id"] + ".loaded.javascript") != null && (int)data.SelectToken(item["type"] + "." + item["id"] + ".loaded.javascript") == 1)
            {
                return true;
            }
            return false;
        }

       
        public string make_request(string module_id, string method_name)
        {
            if (string.IsNullOrEmpty(module_id) || string.IsNullOrEmpty(method_name))
            {
                return "{success: false, msg: '缺少必要的参数！'}";
            }

            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            string group_id = sessionsbll.get_group_id();

            if (string.IsNullOrEmpty(group_id))
            {
                return "{success: false, msg: '您目前未登录'}";
            }

            if (!this.is_group_allowed(group_id,module_id,method_name))
            {
                return "{success: false, msg: '您没有所需的权限！'}";
            }

            QOModulesBLL modulesbll = new QOModulesBLL();
            JObject module = modulesbll.get_by_id(module_id).data;
            if (module != null)
            {
                if (module.SelectToken("server.class")!=null && module.SelectToken("server.file") != null)
                {
                    string file = HttpContext.Current.Server.MapPath((string)module.SelectToken("server.file"));
                    string clsName = (string)module.SelectToken("server.class");
                    Assembly asm = Assembly.LoadFile(file);

                    Object obj = asm.CreateInstance(clsName, true);

                    Type t = obj.GetType();
                    return (string)t.InvokeMember(method_name, BindingFlags.InvokeMethod, null, obj, null);
                }
            }
            return null;
        }

        private bool is_group_allowed(string group_id, string module_id, string method_name)
        {
            QOGroupsBLL groupsbll = new QOGroupsBLL();
            string privilege_id = groupsbll.get_privilege_id(group_id);

            if (privilege_id != null)
            {
                QOPrivilegesBLL privilegesbll = new QOPrivilegesBLL();
                return privilegesbll.is_allowed(privilege_id, module_id, method_name);
            }
            return false;
        }

        public void logout()
        {
            QOSessionsBLL sessionsbll = new QOSessionsBLL();
            throw new NotImplementedException();
        }
    }
}
